package com.jiangjiang.eshop.inventory.service.impl;

import com.jiangjiang.eshop.inventory.async.StockUpdateResultManager;
import com.jiangjiang.eshop.inventory.async.StockUpdateMessage;
import com.jiangjiang.eshop.inventory.async.StockUpdateQueue;
import com.jiangjiang.eshop.inventory.constant.GoodsStockUpdateOperation;
import com.jiangjiang.eshop.inventory.domain.GoodsStockEntity;
import com.jiangjiang.eshop.inventory.service.InventoryGoodsStockService;
import com.jiangjiang.eshop.inventory.updater.*;
import com.jiangjiang.eshop.inventory.service.InventoryService;
import com.jiangjiang.eshop.order.dto.OrderInfoDTO;
import com.jiangjiang.eshop.wms.dto.PurchaseInputOrderDTO;
import com.jiangjiang.eshop.wms.dto.ReturnGoodsInputOrderDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.UUID;

/**
 * @ClassName InventoryFacadeServiceImpl
 * @Description TODO
 * @Author jhw
 * @Date 2021/6/7 19:34
 * @Version 1.0
 **/
@Service
@Slf4j
public class InventoryServiceImpl implements InventoryService {

    @Autowired
    private PurchaseInputStockUpdaterFactory<PurchaseInputOrderDTO> purchaseInputStockFactory;
    @Autowired
    private ReturnInputStockFactory<ReturnGoodsInputOrderDTO> returnInputStockFactory;
    @Autowired
    private SubmitOrderStockUpdaterFactory<OrderInfoDTO> submitOrderStockFactory;
    @Autowired
    private PayOrderStockUpdaterFactory<OrderInfoDTO> payOrderStockFactory;
    @Autowired
    private CancelOrderStockUpdaterFactory<OrderInfoDTO> cancelOrderStockFactory;
    @Autowired
    private InventoryGoodsStockService inventoryGoodsStockService;
    @Autowired
    private StockUpdateQueue stockUpdateQueue;
    @Autowired
    private StockUpdateResultManager stockUpdateResultManager;

    /**
     * 通知库存中心,采购入库完成事件发生了
     *
     * @param purchaseInputOrderDTO 采购入库单DTO
     * @return 处理结果
     */
    @Override
    public Boolean informPurchaseInputFinishedEvent(PurchaseInputOrderDTO purchaseInputOrderDTO) throws Exception {
        try {
            StockUpdater stockUpdater = purchaseInputStockFactory.create(purchaseInputOrderDTO);
            return stockUpdater.updateGoodsStock();
        } catch (Exception e) {
            log.warn("error", e);
        }
        return Boolean.FALSE;
    }

    /**
     * 通知库存中心，“完成退货入库”事件发生了
     *
     * @param returnGoodsInputOrderDTO 退货入库单DTO
     * @return 处理结果
     * @throws Exception
     */
    @Override
    public Boolean informReturnGoodsInputFinished(ReturnGoodsInputOrderDTO returnGoodsInputOrderDTO) throws Exception {
        try {
            StockUpdater stockUpdater = returnInputStockFactory.create(returnGoodsInputOrderDTO);
            return stockUpdater.updateGoodsStock();
        } catch (Exception e) {
            log.warn("error", e);
        }
        return Boolean.FALSE;
    }


    @Override
    public Boolean informSubmitOrderEvent(OrderInfoDTO orderInfoDTO) {
        try {
            StockUpdater stockUpdater = submitOrderStockFactory.create(orderInfoDTO);
            stockUpdater.updateGoodsStock();

            // 发送异步消息到内存队列
            StockUpdateMessage message = new StockUpdateMessage();
            message.setId(UUID.randomUUID().toString().replace("-", ""));
            message.setOperation(GoodsStockUpdateOperation.SUBMIT_ORDER);
            message.setParameter(orderInfoDTO);
            stockUpdateQueue.put(message);

            // 监听异步处理结果
            stockUpdateResultManager.observe(message.getId());
            return Boolean.TRUE;
        } catch (Exception e) {
            log.warn("error", e);
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean informPayOrderEvent(OrderInfoDTO orderInfoDTO) {
        try {
            StockUpdater stockUpdater = payOrderStockFactory.create(orderInfoDTO);
            stockUpdater.updateGoodsStock();
            // 发送异步消息到内存队列
            StockUpdateMessage message = new StockUpdateMessage();
            message.setId(UUID.randomUUID().toString().replace("-", ""));
            message.setOperation(GoodsStockUpdateOperation.PAY_ORDER);
            message.setParameter(orderInfoDTO);
            stockUpdateQueue.put(message);
            // 监听异步处理结果
            stockUpdateResultManager.observe(message.getId());
            return Boolean.TRUE;

        } catch (Exception e) {
            log.warn("error", e);
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean informCancelOrderEvent(OrderInfoDTO orderInfoDTO) {
        try {
            StockUpdater stockUpdater = cancelOrderStockFactory.create(orderInfoDTO);
            stockUpdater.updateGoodsStock();
            // 发送异步消息到内存队列
            StockUpdateMessage message = new StockUpdateMessage();
            message.setId(UUID.randomUUID().toString().replace("-", ""));
            message.setOperation(GoodsStockUpdateOperation.CANCEL_ORDER);
            message.setParameter(orderInfoDTO);
            stockUpdateQueue.put(message);

            // 监听异步处理结果
            stockUpdateResultManager.observe(message.getId());
            return Boolean.TRUE;

        } catch (Exception e) {
            log.warn("error", e);
        }
        return Boolean.FALSE;
    }


    @Override
    public Long getSaleStockQuantity(Long goodsSkuId) {
        GoodsStockEntity goodsStockEntity = inventoryGoodsStockService.queryByGoodsSkuId(goodsSkuId);
        if (Objects.isNull(goodsStockEntity)) {
            return 0L;
        }
        return goodsStockEntity.getSaleStockQuantity();
    }

    @Override
    public Boolean setSaleStockQuantity(Long goodsSkuId, Long saleStockQuantity) {
        GoodsStockEntity goodsStockEntity = inventoryGoodsStockService.queryByGoodsSkuId(goodsSkuId);
        if (goodsStockEntity == null) {
            goodsStockEntity = new GoodsStockEntity();
            goodsStockEntity.setGoodsSkuId(goodsSkuId);
            goodsStockEntity.setSaleStockQuantity(saleStockQuantity);
            goodsStockEntity.setLockedStockQuantity(0L);
            goodsStockEntity.setSaledStockQuantity(0L);
            goodsStockEntity.setStockStatus(saleStockQuantity > 0L ? 1 : 0);
            return inventoryGoodsStockService.save(goodsStockEntity);
        } else {
            goodsStockEntity.setSaleStockQuantity(saleStockQuantity);
            return inventoryGoodsStockService.updateById(goodsStockEntity);
        }

    }
}
